﻿using System;
using System.Collections.Generic;

namespace Framework
{
    public class ObjectPool<T> : IDisposable where T : IPoolable, new()
    {
        private int _maxCount;
        private List<T> _listObject;
        private List<T> _listInuseObject;
        
        public ObjectPool(int count)
        {
            _maxCount = count;
            _listObject = new List<T>(_maxCount);
            _listInuseObject = new List<T>(_maxCount);
        }

        public bool IsUpToMax()
        {
            return _listInuseObject.Count >= _maxCount;
        }

        public T Retain(params object[] args)
        {
            if (!IsUpToMax())
            {
                T poolable;
                int count = _listObject.Count;
                if (count > 0)
                {
                    int lastIndex = count - 1;
                    poolable = _listObject[lastIndex];
                    _listObject.RemoveAt(lastIndex);
                }
                else
                {
                    poolable = new T();
                }
                _listInuseObject.Add(poolable);
                poolable.Retain(args);
                return poolable;
            }
            else
            {
                throw new ArgumentOutOfRangeException();
            }
        }

        public void Release(T poolable)
        {
            poolable.Release();
            int index = _listInuseObject.IndexOf(poolable);
            _listInuseObject.RemoveAt(index);
            _listObject.Add(poolable);
        }
        
        public void Dispose()
        {
            int count = _listObject.Count;
            for (int i = 0; i < count; ++i)
            {
                _listObject[i].Dispose();
            }
            count = _listInuseObject.Count;
            for (int i = 0; i < count; ++i)
            {
                _listInuseObject[i].Dispose();
            }
            _listObject.Clear();
            _listInuseObject.Clear();
        }
    }
}